
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

//根据端口号和IP地址  返回一个监听套接字
int create_socket(short port , char * ipstr)
{
    //创建一个套接字
    int sock = socket(AF_INET , SOCK_STREAM , 0);
    if(sock == -1)
    {
        perror("socket error\n");
        return -1;
    }

    //指定本机的网络地址 ：IP地址和端口号
    struct sockaddr_in Server; 
    Server.sin_family = AF_INET; //指定协议族 
    Server.sin_port = htons(port);//指定端口号 
    Server.sin_addr.s_addr = inet_addr(ipstr);//指定IP地址

    //将本机的网络地址绑定到套接字上面 
    int ret = bind(sock , (struct sockaddr *)&Server , sizeof(Server));
    if(ret == -1)
    {
        perror("bind error\n");
        return -1;
    }

    //监听套接字 
    ret = listen(sock , 10);
    if(ret == -1)
    {
        perror("listen error\n");
        return -1;
    }

    return sock;


}

//子进程处理与客户端的通信
void handle_tcp_client( int confd)
{

    char buf[1024]={0};
    int ret ; 
    while(1)
    {
        ret = recv(confd , buf , 1024 , 0);
        if(ret > 0) //表示读到了数据
        {
            buf[ret] = '\0';
            printf("Recv Data : %s\n",buf);

            char * resp= "Recv Your Data!";
            send(confd , resp ,strlen(resp),0);  

        }


    }






}






// ./a.out port  ip
int main(int argc ,char * argv[])
{
    int sock = create_socket( atoi(argv[1] ), argv[2]  );
    if(sock == -1)
    {
        printf("create_socket error\n");
        return -1;
    }

    //接下来就是要建立连接了 
    //每当有一个客户端申请于服务器端连接时 开辟一个子进程去处理当前客户端于服务器端的通信 
    //而主线继续监听 
    while(1)
    {
        struct sockaddr_in Client; 
        socklen_t len = sizeof(Client);
        int confd = accept(sock, (struct sockaddr *)&Client  , &len);
        if(confd == -1)
        {
            perror("accept error\n");
            return -1;
        }

        //打印客户端的信息 
        printf("connect %s [port : %d]\n",   inet_ntoa ( Client.sin_addr )  ,   ntohs (Client.sin_port)   );

        //创建一个子进程去跟当前连接的客户端进行通信 
        pid_t pid = fork();
        if(pid == -1)
        {
            perror("fork error\n");
            return -1;
        }
        else if(pid == 0)//子进程 
        {
            //子进程处理通信 
            handle_tcp_client(confd);
            exit(0);

        }
        else if(pid > 0)//父进程
        {
            close(confd); //关闭父进程中打开的套接字

        }



    }



}












